﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using InfoJetSoft.Service;
using Microsoft.SharePoint;
using System.Xml;
using System.Xml.XPath;
using System.Text;
using ServBus.ListForm2010.Utility;
using ServBus.ListForm2010.Extension;
using Microsoft.SharePoint.WebControls;
using ServBus.ListForm2010.License;

namespace ServBus.ListForm2010.Layouts.ListForm2010
{
    public partial class ListFormInner : LayoutsPageBase
    {
        #region Parameters

        private static string _webpartMode = string.Empty;//"NEW";
        private static string _siteName;//"http://win-3ststb2hjp7";
        private static Guid _webName;//"Test";
        private static string _listId = "";//"test";
        private static string _ctypeId = "";
        private static string _itemId = "";//string.Empty;
        private static string _viewId = "";//string.Empty;
        private static string _xsnLocation = "";
        private static string _errorMsg = "";
        private static string InfojetServiceAction = "/_layouts/ListForm2010/xdoc.aspx";
        private static string _ctypeName = "";

        private static readonly Dictionary<string, Dictionary<int, string>> SItemsId = new Dictionary<string, Dictionary<int, string>>();

        private static XmlNamespaceManager _xNameSpace;

        #endregion

        private void errorLog(Exception ex, bool internalError)
        {
            if (false)
            {
                errorPanel.Visible = true;
            }
            else
            {
                LTException.Text = ex.Message;
                LTException.Visible = true;
            }
            ErrorLog.Write("ListFormInner" + "\r\n" + Request.Url + "\r\n" + ex.Message + "\r\n" + ex.StackTrace, System.Diagnostics.EventLogEntryType.Error);
        }

        #region Page Method

        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                Activations activations = new Activations(SPContext.Current.Site.WebApplication);
                if (!activations.IsActivationValid(SPContext.Current.Web, out _errorMsg))
                {
                    errorLog(new Exception(_errorMsg), false);
                }
                else
                {
                    InfoJetService.ServiceAction = InfojetServiceAction;
                    InfoJetSoft.Service.Util.ConfigUtil.SetEnableRichText(true);
                    InfoJetSoft.Service.Util.ConfigUtil.EditRichTextOnFocus = true;
                    InfoJetSoft.Service.Util.ConfigUtil.SetEnableFormFieldsCache(true);
                    InfoJetSoft.Service.Util.ConfigUtil.SetEnablePlaceholderUI(true);

                    _webpartMode = Page.Request["wpMode"].ToUpper();
                    _listId = Page.Request["listId"];
                    _ctypeId = Page.Request["ctype"];
                    //viewId = Page.Request["view"];
                    _siteName = SPContext.Current.Site.Url;

                    _webName = SPContext.Current.Web.ID;

                    _xNameSpace = new XmlNamespaceManager(new NameTable());
                    _xNameSpace.AddNamespace("dfs", "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution");
                    _xNameSpace.AddNamespace("tns", "http://tempuri.org/");
                    _xNameSpace.AddNamespace("pc", "http://schemas.microsoft.com/office/infopath/2007/PartnerControls");
                    if (Page.IsPostBack) return;
                    switch (_webpartMode)
                    {
                        case "NEW":
                            GenerateNewForm();
                            break;
                        case "DISP":
                            _itemId = Page.Request["itemId"];
                            GenerateDisplayForm();
                            break;
                        case "EDIT":
                            _itemId = Page.Request["itemId"];
                            GenerateEditForm();
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                errorLog(ex, true);
            }
        }

        protected void DeleteBtn_Click(object sender, EventArgs e)
        {
            try
            {
                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    using (SPSite site = new SPSite(_siteName))
                    {
                        using (SPWeb web = site.OpenWeb(_webName))
                        {
                            web.AllowUnsafeUpdates = true;
                            SPList list = web.Lists[new Guid(_listId)];
                            int itemId = Convert.ToInt32(_itemId);
                            SPListItem item = list.GetItemById(itemId);
                            item.Recycle();
                        }
                    }
                });
                Response.Write("<script type='text/javascript'>parent.window.frameElement.commitPopup('Operation Successful!')</script>");

            }
            catch (Exception ex)
            {
                errorLog(ex, true);
            }
        }

        protected void SaveBtn_Click(object sender, EventArgs e)
        {
            try
            {

                InfoJetContext ijCtx = new InfoJetContext { InlineFileStorage = new InlineFileStorage() };
                InfoJetForm savedForm = InfoJetService.ReloadForm(Context, ijCtx);
                XmlDocument xDoc = new XmlDocument();
                xDoc.LoadXml(savedForm.Xml);

                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    using (SPSite site = new SPSite(_siteName))
                    {
                        using (SPWeb web = site.OpenWeb(_webName))
                        {
                            web.AllowUnsafeUpdates = true;
                            SPList list = web.Lists[new Guid(_listId)];
                            SPContentTypeId contentTypeId = new SPContentTypeId(_ctypeId.ToLower());
                            _ctypeName = list.ContentTypes[contentTypeId].Name;
                            int itemId = 0;

                            if (_webpartMode.Equals("NEW"))
                            {
                                SPListItem newItem = list.Items.Add();
                                newItem["ContentType"] = _ctypeName;
                                newItem.Update();
                                itemId = newItem.ID;
                            }
                            else if (_webpartMode.Equals("EDIT"))
                            {
                                itemId = Convert.ToInt32(_itemId);
                            }
                            SPListItem item = list.GetItemById(itemId);
                            foreach (XmlNode xNode in xDoc.ChildNodes)
                            {
                                SaveListFieldsValue(xNode, list, item);
                            }

                            //Lookupform
                            XmlNode subFormsNode = xDoc.SelectSingleNode("/dfs:myFields/dfs:dataFields/tns:mainForm/tns:SubForms", _xNameSpace);
                            if (subFormsNode != null)
                            {
                                if (CheckLkpItemModified(subFormsNode))
                                {
                                    SaveLkpFormValue(subFormsNode, item);
                                }
                                else
                                {
                                    xDocViewInner.Visible = true;
                                    errorPanel.Visible = true;
                                    string errorMessage =
                                        "Some corresponding List Items has been changed, please refresh or reopen the input form!";
                                    LTException.Text = errorMessage;
                                    ErrorLog.Write(errorMessage, EventLogEntryType.Error);
                                }
                            }
                            item.Update();
                        }
                    }
                });
                //Response.Write("<script type='text/javascript'>window.close()</script>");
                Response.Write("<script type='text/javascript'>parent.window.frameElement.commitPopup('Operation Successful')</script>");
            }
            catch (Exception ex)
            {
                errorLog(ex, true);
            }
        }

        #endregion

        #region Private Method

        private void GenerateDisplayForm()
        {
            SItemsId.Clear();
            string xmlTemplate = GetXMLTemplate().Xml;
            if (xmlTemplate != string.Empty)
            {
                XmlDocument xDoc = new XmlDocument();
                xDoc.LoadXml(xmlTemplate);


                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    using (SPSite site = new SPSite(_siteName))
                    {
                        using (SPWeb web = site.OpenWeb(_webName))
                        {
                            SPList list = web.Lists[new Guid(_listId)];
                            SPContentTypeId contentTypeId = new SPContentTypeId(_ctypeId.ToLower());
                            _ctypeName = list.ContentTypes[contentTypeId].Name;
                            int itemId = Convert.ToInt32(_itemId);
                            SPListItem item = list.GetItemById(itemId);
                            foreach (XmlNode xNode in xDoc.ChildNodes)
                            {
                                SetListFieldsValue(xNode, list, item);
                            }

                            XmlNode subFormsNode = xDoc.SelectSingleNode("/dfs:myFields/dfs:dataFields/tns:mainForm/tns:SubForms", _xNameSpace);
                            if (subFormsNode != null)
                            {
                                SetLkpFormValue(subFormsNode, itemId);
                            }

                            InfoJetContext ijCtx = new InfoJetContext
                            {
                                InlineFileStorage = new InlineFileStorage(),
                                ExportFileStorage = new ExportFileStorage()
                            };
                            RelativeUrlResolver resolver = new RelativeUrlResolver(_xsnLocation);
                            ijCtx.RelativeUrlResolver = resolver;
                            ijCtx.IsReadonly = true;
                            if (!string.IsNullOrEmpty(_viewId))
                            {
                                ijCtx.ViewName = _viewId;
                            }
                            InfoJetForm editForm = InfoJetService.BuildFormByXML(Context, ijCtx, _xsnLocation, xDoc.OuterXml);

                            xDocViewInner.Text = editForm.Xhtml;
                        }
                    }
                });
            }
        }

        private void GenerateNewForm()
        {
            SItemsId.Clear();
            InfoJetForm newForm = GetXMLTemplate();

            if (newForm != null)
            {
                InfoJetContext ijCtx = new InfoJetContext
                {
                    InlineFileStorage = new InlineFileStorage(),
                    ExportFileStorage = new ExportFileStorage()
                };
                RelativeUrlResolver resolver = new RelativeUrlResolver(_xsnLocation);
                ijCtx.RelativeUrlResolver = resolver;
                if (!string.IsNullOrEmpty(_viewId))
                {
                    ijCtx.ViewName = _viewId;
                }
                InfoJetForm editForm = InfoJetService.BuildFormByXML(Context, ijCtx, _xsnLocation, newForm.Xml);
                xDocViewInner.Text = editForm.Xhtml;

                //this.xDocViewInner.Text = newForm.Xhtml;
            }
        }

        private void GenerateEditForm()
        {
            SItemsId.Clear();
            string xmlTemplate = GetXMLTemplate().Xml;
            if (xmlTemplate != string.Empty)
            {
                XmlDocument xDoc = new XmlDocument();
                xDoc.LoadXml(xmlTemplate);

                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    using (SPSite site = new SPSite(_siteName))
                    {
                        using (SPWeb web = site.OpenWeb(_webName))
                        {
                            SPList list = web.Lists[new Guid(_listId)];
                            SPContentTypeId contentTypeId = new SPContentTypeId(_ctypeId.ToLower());
                            _ctypeName = list.ContentTypes[contentTypeId].Name;
                            int itemId = Convert.ToInt32(_itemId);
                            SPListItem item = list.GetItemById(itemId);
                            foreach (XmlNode xNode in xDoc.ChildNodes)
                            {
                                SetListFieldsValue(xNode, list, item);
                            }
                            //Lookupform
                            XmlNode subFormsNode = xDoc.SelectSingleNode("/dfs:myFields/dfs:dataFields/tns:mainForm/tns:SubForms", _xNameSpace);
                            if (subFormsNode != null)
                            {
                                SetLkpFormValue(subFormsNode, itemId);
                            }

                            InfoJetContext ijCtx = new InfoJetContext
                            {
                                InlineFileStorage = new InlineFileStorage(),
                                ExportFileStorage = new ExportFileStorage()
                            };
                            RelativeUrlResolver resolver = new RelativeUrlResolver(_xsnLocation);
                            ijCtx.RelativeUrlResolver = resolver;
                            if (!string.IsNullOrEmpty(_viewId))
                            {
                                ijCtx.ViewName = _viewId;
                            }
                            InfoJetForm editForm = InfoJetService.BuildFormByXML(Context, ijCtx, _xsnLocation, xDoc.OuterXml);
                            xDocViewInner.Text = editForm.Xhtml;
                        }
                    }
                });
            }
        }

        private static Dictionary<string, string> GetViewConfigItem(SPWeb web, string mListID, string mContentTypeID)
        {
            Dictionary<string, string> views = new Dictionary<string, string>();
            if (string.IsNullOrEmpty(mListID) || string.IsNullOrEmpty(mContentTypeID)) return views;
            try
            {
                SPList configList = web.Lists[Constants.LookupForm_Config_NAME];
                SPQuery query = new SPQuery
                {
                    Query =
                        "<Where><And><Eq><FieldRef Name='Title' /><Value Type='Text'>" + mListID +
                        "</Value></Eq><Eq><FieldRef Name='mContentType' /><Value Type='Text'>" + mContentTypeID +
                        "</Value></Eq></And></Where>"
                };
                SPListItemCollection items = configList.GetItems(query);
                if (items.Count > 0)
                {
                    string dispView = Convert.ToString(items[0]["mDispView"]);
                    string editView = Convert.ToString(items[0]["mEditView"]);
                    string newView = Convert.ToString(items[0]["mNewView"]);

                    if (!string.IsNullOrEmpty(dispView))
                    {
                        views.Add("DISP", dispView);
                        views.Add("EDIT", editView);
                        views.Add("NEW", newView);
                    }

                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            return views;
        }

        private bool RegisterXSNTemplate()
        {
            Guid xsnId;

            byte[] xsnContent;

            bool succeed = false;
            InfoJetService.License(Constants.InfoJetLicense);



            SPSecurity.RunWithElevatedPrivileges(delegate
            {
                using (SPSite site = new SPSite(_siteName))
                {
                    using (SPWeb web = site.OpenWeb(_webName))
                    {
                        SPList list = web.Lists[new Guid(_listId)];
                        SPContentTypeId contentTypeId = new SPContentTypeId(_ctypeId.ToLower());
                        SPContentType cType = list.ContentTypes[contentTypeId];
                        _xsnLocation = web.Url + "/" + cType.ResourceFolder.Url + "/template.xsn";

                        SPFile file = web.GetFile(_xsnLocation);
                        xsnContent = file.OpenBinary();
                        xsnId = file.UniqueId;


                        if (xsnContent == null)
                        {
                            succeed = false;
                        }
                        else
                        {
                            string md5 = CryptoUtility.ComputeMD5(xsnContent);
                            if (InfoJetService.GetMD5(_xsnLocation) == md5)
                            {
                                succeed = true;
                            }
                            else
                            {
                                InfoJetContext ijCtx = new InfoJetContext();
                                ijCtx.Variables.Add("InfoBus_XsnId", xsnId.ToString());
                                ijCtx.ResourceFileStorage = new ResourceFileStorage(web);
                                ijCtx.InlineFileStorage = new InlineFileStorage();
                                succeed = InfoJetService.RegisterWithMD5(Context, ijCtx, _xsnLocation, xsnContent, "/_layouts/ListForm2010/", md5);
                            }
                        }
                        Dictionary<string, string> views = GetViewConfigItem(web, Convert.ToString(list.ID), Convert.ToString(cType.Id));
                        _webpartMode = Page.Request["wpMode"].ToUpper();
                        if (views.ContainsKey(_webpartMode))
                        {
                            _viewId = views[_webpartMode];
                        }
                    }
                }
            });
            return succeed;
        }

        private InfoJetForm GetXMLTemplate()
        {
            if (RegisterXSNTemplate())
            {

                InfoJetContext ijCtx = new InfoJetContext
                {
                    InlineFileStorage = new InlineFileStorage(),
                    ExportFileStorage = new ExportFileStorage()
                };
                RelativeUrlResolver resolver = new RelativeUrlResolver(_xsnLocation);
                ijCtx.RelativeUrlResolver = resolver;
                //if (!string.IsNullOrEmpty(viewId))
                //{
                //    ijCtx.ViewName = viewId;
                //}
                InfoJetForm newForm = InfoJetService.BuildFormByTemplate(Context, _xsnLocation, ijCtx);
                return newForm;
            }
            return null;
        }

        private void SetListFieldsValue(XmlNode xNode, SPList plist, SPListItem p_Item)
        {
            if (xNode.LocalName != "SubForms")
            {
                if (xNode.HasChildNodes)
                {
                    foreach (XmlNode cXNode in xNode.ChildNodes)
                    {
                        SetListFieldsValue(cXNode, plist, p_Item);
                    }
                }
                SetValue(xNode.CreateNavigator(), plist, p_Item);
            }
        }

        private void SetLkpFormValue(XmlNode xNode, int itemId)
        {
            //ListNode
            foreach (XmlNode listNode in xNode.ChildNodes)
            {
                XmlNode node = listNode;
                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    using (SPSite site = new SPSite(_siteName))
                    {
                        using (SPWeb web = site.OpenWeb(_webName))
                        {
                            web.AllowUnsafeUpdates = true;
                            if (node.Attributes != null)
                            {
                                string sListId = node.Attributes[0].Value;
                                SPList mList = web.Lists[new Guid(_listId)];
                                SPList slist = web.Lists[new Guid(sListId)];
                                List<XmlNode> addSContentTypeNode = new List<XmlNode>();
                                foreach (XmlNode sContentTypeNode in node.ChildNodes)
                                {
                                    if (sContentTypeNode.Attributes != null)
                                    {
                                        string sContentTypeId = sContentTypeNode.Attributes[0].Value;
                                        SPContentType sContentType = slist.ContentTypes[new SPContentTypeId(sContentTypeId)];
                                        _ctypeName = sContentType.Name;
                                        SPListItemCollection resultItems = GetLkpSubItems(mList, slist, itemId, sContentType.Name);
                                        foreach (SPListItem sItem in resultItems)
                                        {
                                            XmlNode sItemNode = sContentTypeNode.Clone();
                                            sItemNode.CreateNavigator();
                                            //sItemNav.CreateAttribute("", "ItemID", "", sItem.ID.ToString());
                                            if (sItemNode.Attributes != null)
                                                sItemNode.Attributes["Item_ID"].Value = sItem.ID.ToString(CultureInfo.InvariantCulture);

                                            foreach (XmlNode sFieldNode in sItemNode.ChildNodes)
                                            {
                                                SetValue(sFieldNode.CreateNavigator(), slist, sItem);
                                            }

                                            //XPathNavigator listNav = rootNav.SelectSingleNode(string.Format("/dfs:myFields/dfs:dataFields/tns:mainForm/tns:SubForms/tns:{0}", listNode.LocalName), xNameSpace);
                                            //listNav.AppendChild(sItemNav);
                                            addSContentTypeNode.Add(sItemNode);
                                        }
                                    }
                                }

                                node.RemoveAll();
                                XPathNavigator listNav = node.CreateNavigator();
                                listNav.CreateAttribute("tns", "List_ID", "http://tempuri.org/", sListId);
                                foreach (XmlNode addNode in addSContentTypeNode)
                                {
                                    node.AppendChild(addNode);
                                }
                            }
                        }
                    }
                });
            }
        }

        private SPListItemCollection GetLkpSubItems(SPList mList, SPList sList, int itemId, string ctName)
        {
            SPListItemCollection resultItems = null;

            SPField lkpField = GetLkpField(mList, sList, ctName);

            if (!string.IsNullOrEmpty(lkpField.Title))
            {
                SPQuery query = new SPQuery
                {
                    Query = string.Format("<Where><And><Eq><FieldRef Name='{0}' LookupId='TRUE' />" +
                                          "<Value Type='Lookup'>{1}</Value></Eq><Eq><FieldRef Name='ContentType' /><Value Type='Text'>{2}</Value></Eq></And></Where>",
                        lkpField.InternalName, itemId, ctName)
                };
                sList.GetItems(query);
                if (!SItemsId.ContainsKey(sList.Title))
                {
                    resultItems = sList.GetItems(query);
                    Dictionary<int, string> itemIds = new Dictionary<int, string>();
                    foreach (SPListItem item in resultItems)
                    {
                        itemIds.Add(item.ID, Convert.ToString(item["Modified"]));
                    }
                    SItemsId.Add(sList.Title, itemIds);
                }
                else
                {
                    resultItems = sList.GetItems(query);
                    Dictionary<int, string> itemIds = SItemsId[sList.Title];
                    foreach (SPListItem item in resultItems)
                    {
                        if (!itemIds.ContainsKey(item.ID))
                        {
                            itemIds.Add(item.ID, Convert.ToString(item["Modified"]));
                        }
                    }
                }
            }
            return resultItems;
        }

        private SPField GetLkpField(SPList mList, SPList sList, string ctName)
        {
            SPField lkpField = null;
            SPContentType ctype = sList.ContentTypes[ctName];
            //Find lkp Field
            foreach (SPField sField in ctype.Fields)
            {
                if (sField.Type.Equals(SPFieldType.Lookup))
                {
                    SPFieldLookup sLkpField = (SPFieldLookup)sField;
                    Guid sLkpID = new Guid(sLkpField.LookupList);
                    if (sLkpID.Equals(mList.ID))
                    {
                        lkpField = sLkpField;
                        break;
                    }
                }
            }

            return lkpField;
        }

        private void SetValue(XPathNavigator p_XPathNav, SPList plist, SPListItem p_Item)
        {
            if (p_XPathNav != null)
            {
                string uniquePrefix = string.Format("{0}_{1}_", plist.Title, _ctypeName).Replace(" ", "_");
                string localName = p_XPathNav.LocalName.Replace(uniquePrefix, "");

                //begin looping through the nodes
                if (localName != null)
                {
                    #region Set Value

                    string mFieldInternalName = localName;
                    if (plist.Fields.ContainsField(mFieldInternalName))
                    {
                        SPField mField = plist.Fields.GetField(mFieldInternalName);

                        string mFieldValue = GetFormValueFromField(mField, p_Item);

                        if (string.IsNullOrEmpty(mFieldValue))
                        {
                            return;
                        }

                        //根据不同的Field类型，表单对应不同的数据类型，这里需要判断
                        switch (mField.Type)
                        {
                            case SPFieldType.Number:
                                DeleteNil(p_XPathNav);
                                p_XPathNav.SetValue(mFieldValue);
                                break;

                            case SPFieldType.DateTime:
                                DeleteNil(p_XPathNav);
                                SPFieldDateTime dateTimeField = (SPFieldDateTime)mField;
                                //DateOnly
                                if (dateTimeField.DisplayFormat == SPDateTimeFieldFormatType.DateOnly)
                                {
                                    DateTime dt = DateTime.Parse(mFieldValue);
                                    p_XPathNav.SetValue(dt.Date.ToString("yyyy-MM-dd"));
                                }
                                else
                                {
                                    DateTime dt = DateTime.Parse(mFieldValue);
                                    p_XPathNav.SetValue(dt.Date.ToString("s"));
                                }
                                break;

                            case SPFieldType.User:
                                //if (p_xPathNav.InnerXml == "")
                                //{
                                //    return;
                                //}
                                InsertToUserType(p_Item, mField.Title, p_XPathNav);
                                break;

                            case SPFieldType.MultiChoice:
                                InsertIntoCheckBoxType(mFieldValue, p_XPathNav, p_XPathNav.LocalName);
                                break;

                            case SPFieldType.Note:
                                SPFieldMultiLineText noteField = (SPFieldMultiLineText)mField;
                                if (noteField.RichText)
                                {
                                    p_XPathNav.InnerXml = mFieldValue;
                                }
                                else
                                {
                                    p_XPathNav.InnerXml = noteField.GetFieldValueAsText(p_Item[mFieldInternalName]);
                                }
                                break;
                            case SPFieldType.Lookup:
                                p_XPathNav.SetValue(mFieldValue);
                                break;

                            default:
                                p_XPathNav.SetValue(mFieldValue);
                                break;
                        }
                    }
                    #endregion
                }
            }
        }

        private void SaveListFieldsValue(XmlNode xNode, SPList plist, SPListItem p_Item)
        {
            if (xNode.LocalName != "SubForms")
            {
                if (xNode.HasChildNodes)
                {
                    foreach (XmlNode cXNode in xNode.ChildNodes)
                    {
                        SaveListFieldsValue(cXNode, plist, p_Item);
                    }
                }
                SaveValue(xNode.CreateNavigator(), plist, p_Item);
            }
        }

        private bool CheckLkpItemModified(XmlNode xNode)
        {
            bool itemStable = true;
            //ListNode
            foreach (XmlNode listNode in xNode.ChildNodes)
            {
                XmlNode node = listNode;
                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    using (SPSite site = new SPSite(_siteName))
                    {
                        using (SPWeb web = site.OpenWeb(_webName))
                        {
                            web.AllowUnsafeUpdates = true;
                            SPList mList = web.Lists[new Guid(_listId)];
                            if (node.Attributes == null) return;
                            string sListId = node.Attributes[0].Value;
                            SPList slist = web.Lists[new Guid(sListId)];

                            Dictionary<int, string> itemIds = new Dictionary<int, string>();
                            if (SItemsId.ContainsKey(slist.Title))
                            {
                                itemIds = SItemsId[slist.Title];
                            }
                            foreach (XmlNode sItemNode in node.ChildNodes)
                            {
                                if (sItemNode.Attributes != null)
                                {
                                    string sContentTypeId = sItemNode.Attributes[0].Value;
                                    SPContentType sContentType = slist.ContentTypes[new SPContentTypeId(sContentTypeId)];

                                    GetLkpField(mList, slist, sContentType.Name);
                                }
                                if (!_webpartMode.Equals("EDIT")) continue;
                                if (sItemNode.Attributes == null) continue;
                                XmlAttribute sItemIDAttr = sItemNode.Attributes["Item_ID"];
                                if (sItemIDAttr == null) continue;
                                if (sItemIDAttr.Value == "") continue;
                                int itemId = Convert.ToInt32(sItemIDAttr.Value);
                                if (itemIds.ContainsKey(itemId))
                                {
                                    SPListItem editItem = slist.GetItemById(itemId);
                                    if (itemIds[itemId] != Convert.ToString(editItem["Modified"]))
                                    {
                                        itemStable = false;
                                    }
                                }
                                //Check editItem has modified?
                            }
                        }
                    }
                });
            }

            return itemStable;
        }

        private void SaveLkpFormValue(XmlNode xNode, SPListItem item)
        {
            //ListNode
            foreach (XmlNode listNode in xNode.ChildNodes)
            {
                XmlNode node = listNode;
                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    using (SPSite site = new SPSite(_siteName))
                    {
                        using (SPWeb web = site.OpenWeb(_webName))
                        {
                            web.AllowUnsafeUpdates = true;
                            SPList mList = web.Lists[new Guid(_listId)];
                            if (node.Attributes != null)
                            {
                                string sListId = node.Attributes[0].Value;
                                SPList slist = web.Lists[new Guid(sListId)];

                                Dictionary<int, string> itemIds = new Dictionary<int, string>();
                                if (SItemsId.ContainsKey(slist.Title))
                                {
                                    itemIds = SItemsId[slist.Title];
                                }
                                foreach (XmlNode sItemNode in node.ChildNodes)
                                {
                                    if (sItemNode.Attributes != null)
                                    {
                                        string sContentTypeId = sItemNode.Attributes[0].Value;
                                        SPContentType sContentType = slist.ContentTypes[new SPContentTypeId(sContentTypeId)];
                                        _ctypeName = sContentType.Name;
                                        SPField lkpField = GetLkpField(mList, slist, sContentType.Name);
                                        if (_webpartMode.Equals("NEW"))
                                        {
                                            if (!CheckItemNodeEmpty(sItemNode, slist))
                                            {
                                                SPListItem newItem = slist.Items.Add();
                                                newItem["ContentType"] = sContentType.Name;
                                                newItem.Update();
                                                foreach (XmlNode sFieldNode in sItemNode.ChildNodes)
                                                {
                                                    SaveValue(sFieldNode.CreateNavigator(), slist, newItem);
                                                }
                                                newItem[lkpField.Title] = new SPFieldLookupValue(item.ID, item.Title);
                                                newItem.Update();
                                            }
                                        }
                                        else if (_webpartMode.Equals("EDIT"))
                                        {
                                            XmlAttribute sItemIDAttr = sItemNode.Attributes["Item_ID"];
                                            bool sItemIDAttrEmpty = true;
                                            if (sItemIDAttr != null)
                                            {
                                                if (sItemIDAttr.Value != "")
                                                {
                                                    sItemIDAttrEmpty = false;
                                                    int itemId = Convert.ToInt32(sItemIDAttr.Value);
                                                    if (itemIds.ContainsKey(itemId))
                                                    {
                                                        SPListItem editItem = slist.GetItemById(itemId);
                                                        foreach (XmlNode sFieldNode in sItemNode.ChildNodes)
                                                        {
                                                            SaveValue(sFieldNode.CreateNavigator(), slist, editItem);
                                                        }
                                                        editItem[lkpField.Title] = new SPFieldLookupValue(item.ID, item.Title);
                                                        editItem.Update();

                                                        itemIds.Remove(itemId);
                                                    }
                                                }
                                            }
                                            if(sItemIDAttrEmpty)
                                            {
                                                if (!CheckItemNodeEmpty(sItemNode, slist))
                                                {
                                                    SPListItem newItem = slist.Items.Add();
                                                    newItem["ContentType"] = sContentType.Name;
                                                    newItem.Update();
                                                    foreach (XmlNode sFieldNode in sItemNode.ChildNodes)
                                                    {
                                                        SaveValue(sFieldNode.CreateNavigator(), slist, newItem);
                                                    }

                                                    newItem[lkpField.Title] = new SPFieldLookupValue(item.ID, item.Title);
                                                    newItem.Update();
                                                }
                                            }
                                        }
                                    }
                                }

                                foreach (int delItemId in itemIds.Keys)
                                {
                                    slist.Items.DeleteItemById(delItemId);
                                }
                            }
                        }
                    }
                });
            }
        }

        private void SaveValue(XPathNavigator p_XPathNav, SPList plist, SPListItem p_Item)
        {
            if (p_XPathNav != null)
            {
                string uniquePrefix = string.Format("{0}_{1}_", plist.Title, _ctypeName).Replace(" ", "_");
                string localName = p_XPathNav.LocalName.Replace(uniquePrefix, "");

                //begin looping through the nodes
                if (localName != null && localName != "ID")
                {
                    string mFieldInternalName = localName;
                    if (plist.Fields.ContainsField(mFieldInternalName))
                    {
                        SPField mField = plist.Fields.GetField(mFieldInternalName);
                        SPFieldType mFieldType = mField.Type;
                        //单独处理CheckBox
                        if (mFieldType.Equals(SPFieldType.Boolean))
                        {
                            if (!string.IsNullOrEmpty(p_XPathNav.Value))
                            {
                                p_Item[mField.Id] = Convert.ToBoolean(p_XPathNav.Value);
                            }
                            else
                            {
                                p_Item[mField.Id] = false;
                            }
                            p_Item.Update();
                        }
                        else if (!string.IsNullOrEmpty(p_XPathNav.Value))
                        {
                            if (mFieldType.Equals(SPFieldType.MultiChoice))
                            {
                                if (p_XPathNav.MoveToFirstChild())
                                {
                                    SPFieldMultiChoiceValue values = new SPFieldMultiChoiceValue();
                                    do
                                    {
                                        string fieldvalue = p_XPathNav.Value;
                                        if (!string.IsNullOrEmpty(fieldvalue))
                                        {
                                            values.Add(fieldvalue);
                                        }
                                    }
                                    while (p_XPathNav.MoveToNext());
                                    p_Item[mField.Id] = values;
                                    p_Item.Update();
                                }
                            }
                            else if (mFieldType.Equals(SPFieldType.Note))
                            {
                                object mFieldValue = GetFieldValueByType(mFieldType, p_XPathNav.InnerXml);
                                p_Item[mField.Id] = mFieldValue;
                                p_Item.Update();
                            }
                            else if (mFieldType.Equals(SPFieldType.User))
                            {
                                _xNameSpace.AddNamespace("pc", "http://schemas.microsoft.com/office/infopath/2007/PartnerControls");
                                SPFieldUserValueCollection uvc = new SPFieldUserValueCollection();
                                if (p_XPathNav.HasChildren)
                                {
                                    SPSecurity.RunWithElevatedPrivileges(delegate
                                    {
                                        using (SPSite site = new SPSite(_siteName))
                                        {
                                            using (SPWeb web = site.OpenWeb(_webName))
                                            {
                                                p_XPathNav.MoveToFirstChild();
                                                do
                                                {
                                                    XPathNavigator nav = p_XPathNav.SelectSingleNode("./pc:AccountId", _xNameSpace);
                                                    if (nav != null)
                                                    {
                                                        SPUser user = (SPUser)GetFieldValueByType(mFieldType, nav.Value);
                                                        uvc.Add(new SPFieldUserValue(web, user.ID, user.Name));
                                                    }
                                                }
                                                while (p_XPathNav.MoveToNext());
                                            }
                                        }
                                    });
                                    p_Item[mField.Id] = uvc;
                                    p_Item.Update();
                                }
                                else
                                {
                                    p_Item[mField.Id] = "";
                                    p_Item.Update();
                                }
                                //XPathNavigator nav = p_xPathNav.SelectSingleNode("./pc:Person/pc:AccountId", xNameSpace);
                                //while (nav.MoveToFirstChild())
                                //{
                                //    //p_xPathNav.MoveToChild("AccountId", "http://schemas.microsoft.com/office/infopath/2007/PartnerControls");
                                //    object m_field_value = GetFieldValueByType(m_field_type, nav.Value);
                                //    p_item[m_field.Id] = m_field_value;
                                //    p_item.Update();
                                //}
                            }
                            else
                            {
                                object mFieldValue = GetFieldValueByType(mFieldType, p_XPathNav.Value);
                                p_Item[mField.Id] = mFieldValue;
                                p_Item.Update();
                            }
                        }
                    }
                }
            }
        }

        private bool CheckItemNodeEmpty(XmlNode sItemNode, SPList plist)
        {
            //bool rStatus = true;
            foreach (XmlNode sFieldNode in sItemNode.ChildNodes)
            {
                if (!string.IsNullOrEmpty(GetItemNodeValue(sFieldNode.CreateNavigator(), plist)))
                {
                    //rStatus = false;
                    return false;
                }
            }
            return true;
            //return rStatus;
        }

        private string GetItemNodeValue(XPathNavigator p_XPathNav, SPList plist)
        {
            string itemValue = string.Empty;

            if (p_XPathNav != null)
            {
                //string localName = Convert.ToString(p_XPathNav.GetAttribute("Field_Name", ""));
                string uniquePrefix = string.Format("{0}_{1}_", plist.Title, _ctypeName).Replace(" ", "_");
                string localName = p_XPathNav.LocalName.Replace(uniquePrefix, "");

                //begin looping through the nodes
                if (localName != null && localName != "ID")
                {
                    string mFieldInternalName = localName;
                    if (plist.Fields.ContainsField(mFieldInternalName))
                    {
                        SPField mField = plist.Fields.GetField(mFieldInternalName);
                        SPFieldType mFieldType = mField.Type;
                        //单独处理CheckBox
                        if (mFieldType.Equals(SPFieldType.Boolean))
                        {
                            if (!string.IsNullOrEmpty(p_XPathNav.Value))
                            {
                                itemValue = p_XPathNav.Value;
                            }
                        }
                        else if (!string.IsNullOrEmpty(p_XPathNav.Value))
                        {
                            if (mFieldType.Equals(SPFieldType.MultiChoice))
                            {
                                if (p_XPathNav.MoveToFirstChild())
                                {
                                    do
                                    {
                                        itemValue += p_XPathNav.Value;
                                    }
                                    while (p_XPathNav.MoveToNext());
                                }
                            }
                            else if (mFieldType.Equals(SPFieldType.Note))
                            {
                                itemValue = p_XPathNav.InnerXml;
                            }
                            else if (mFieldType.Equals(SPFieldType.User))
                            {
                                SPFieldUserValueCollection uvc = new SPFieldUserValueCollection();
                                if (p_XPathNav.HasChildren)
                                {
                                    SPSecurity.RunWithElevatedPrivileges(delegate
                                    {
                                        using (SPSite site = new SPSite(_siteName))
                                        {
                                            using (SPWeb web = site.OpenWeb(_webName))
                                            {
                                                p_XPathNav.MoveToFirstChild();
                                                do
                                                {
                                                    XPathNavigator nav = p_XPathNav.SelectSingleNode("./pc:AccountId", _xNameSpace);
                                                    if (nav != null)
                                                    {
                                                        SPUser user = (SPUser)GetFieldValueByType(mFieldType, nav.Value);
                                                        uvc.Add(new SPFieldUserValue(web, user.ID, user.Name));
                                                    }
                                                }
                                                while (p_XPathNav.MoveToNext());
                                            }
                                        }
                                    });
                                    itemValue = "User";
                                }
                                else
                                {
                                    itemValue = "";
                                }
                                //XPathNavigator nav = p_xPathNav.SelectSingleNode("./pc:Person/pc:AccountId", xNameSpace);
                                //while (nav.MoveToFirstChild())
                                //{
                                //    //p_xPathNav.MoveToChild("AccountId", "http://schemas.microsoft.com/office/infopath/2007/PartnerControls");
                                //    object m_field_value = GetFieldValueByType(m_field_type, nav.Value);
                                //    p_item[m_field.Id] = m_field_value;
                                //    p_item.Update();
                                //}
                            }
                            else
                            {
                                object mFieldValue = GetFieldValueByType(mFieldType, p_XPathNav.Value);
                                itemValue = Convert.ToString(mFieldValue);
                            }
                        }
                    }
                }
            }
            return itemValue;
        }

        //通过SPField的Type，返回不同的对象，给Item的属性赋值。
        private object GetFieldValueByType(SPFieldType p_Field_Type, string p_Str_Value)
        {
            object mFieldValue = null;
            SPSecurity.RunWithElevatedPrivileges(delegate
            {
                using (SPSite site = new SPSite(_siteName))
                {
                    using (SPWeb web = site.OpenWeb(_webName))
                    {
                        web.AllowUnsafeUpdates = true;
                        switch (p_Field_Type)
                        {
                            case SPFieldType.Text:
                                mFieldValue = p_Str_Value;
                                break;
                            case SPFieldType.User:
                                try
                                {
                                    SPUser mUser = web.EnsureUser(p_Str_Value);
                                    mFieldValue = mUser;
                                }
                                catch (Exception ex)
                                {
                                    Console.WriteLine(ex.ToString());
                                }
                                break;
                            case SPFieldType.Integer:
                                int mInteger = int.Parse(p_Str_Value);
                                mFieldValue = mInteger;
                                break;
                            case SPFieldType.Number:
                                double mNumber = double.Parse(p_Str_Value);
                                mFieldValue = mNumber;
                                break;
                            case SPFieldType.Lookup:
                                SPFieldLookupValue mLookupValue = new SPFieldLookupValue(p_Str_Value);
                                mFieldValue = mLookupValue;
                                break;
                            case SPFieldType.Boolean:
                                mFieldValue = Convert.ToBoolean(p_Str_Value);
                                break;
                            case SPFieldType.Note:
                                string mString = Convert.ToString(p_Str_Value);
                                mString = FormatXhtmlString(mString);
                                mFieldValue = mString;
                                break;
                            default:
                                mFieldValue = p_Str_Value;
                                break;
                        }
                    }
                }
            });

            return mFieldValue;
        }

        private static string FormatXhtmlString(string m_String)
        {
            while (m_String.Contains("/>"))
            {
                int firstIndex = m_String.IndexOf("/>", StringComparison.Ordinal);
                string subMString = m_String.Substring(0, firstIndex);
                string subMStringLater = m_String.Substring(firstIndex + 2);
                int lastIndex = subMString.LastIndexOf("<", StringComparison.Ordinal) + 1;
                int spaceIndex = subMString.IndexOf(" ", lastIndex, StringComparison.Ordinal);
                string tagName = subMString.Substring(lastIndex, spaceIndex - lastIndex);
                subMString = subMString + "></" + tagName + ">";
                m_String = subMString + subMStringLater;

            }
            //m_string = m_string.Replace("\r\n", "<BR>");
            return m_String;
        }
        /// <summary>
        /// 从列表的Field中获取值填充到InfoPath节点中
        /// </summary>
        /// <param name="p_Field"></param>
        /// <param name="p_Item"></param>
        /// <returns></returns>
        private string GetFormValueFromField(SPField p_Field, SPListItem p_Item)
        {

            string mStrValue = string.Empty;
            try
            {

                if (p_Item[p_Field.Id] == null)
                {
                    return mStrValue;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                return mStrValue;
            }


            switch (p_Field.Type)
            {
                case SPFieldType.Lookup:
                    string mLookupValue = p_Item[p_Field.Id].ToString();

                    int tIndex = mLookupValue.IndexOf("#", StringComparison.Ordinal);
                    mStrValue = mLookupValue.Substring(0, tIndex - 1);
                    //m_str_value = m_lookup_value;                   //读取数据时出错。TO DO...目前先临时改回来
                    break;

                case SPFieldType.DateTime:
                    DateTime mTime = (DateTime)p_Item[p_Field.Id];
                    mStrValue = Convert.ToString(mTime);
                    break;

                case SPFieldType.Note:
                    //Obsolete

                    mStrValue = Convert.ToString(p_Item[p_Field.Id]);
                    mStrValue = GetMulitTextString(mStrValue);
                    break;

                case SPFieldType.URL:
                    SPFieldUrlValue urlValue = new SPFieldUrlValue(Convert.ToString(p_Item[p_Field.Id]));
                    mStrValue = urlValue.Url;
                    break;

                case SPFieldType.Boolean:
                    bool booleanField = Convert.ToBoolean(p_Item[p_Field.Id]);
                    mStrValue = booleanField ? "true" : "false";
                    break;

                default:
                    mStrValue = Convert.ToString(p_Item[p_Field.Id]);
                    break;
            }
            return mStrValue;
        }

        /// <summary>
        /// 架构验证发现无数据类型错误的解决方案，目前只用于数字类型
        /// </summary>
        /// <param name="node">当前节点</param>
        private void DeleteNil(XPathNavigator node)
        {
            if (node.MoveToAttribute("nil", "http://www.w3.org/2001/XMLSchema-instance"))
            {
                node.DeleteSelf();
            }
        }

        /// <summary>
        /// 插入用户信息到pc:Person类型的节点中
        /// </summary>
        /// <param name="fieldTitle"></param>
        /// <param name="xPathNav"></param>
        /// <param name="item"></param>
        private void InsertToUserType(SPListItem item, string fieldTitle, XPathNavigator xPathNav)
        {
            string pcValue;
            if (xPathNav.HasChildren)
            {
                xPathNav.SetValue("");
            }
            SPSecurity.RunWithElevatedPrivileges(delegate
            {
                using (SPSite site = new SPSite(_siteName))
                {
                    using (site.OpenWeb(_webName))
                    {
                        try
                        {
                            SPFieldUser userField = (SPFieldUser)item.Fields[fieldTitle];
                            SPFieldUserValue userValue = (SPFieldUserValue)userField.GetFieldValue(Convert.ToString(item[fieldTitle]));
                            SPUser user = userValue.User;
                            pcValue = "<pc:Person><pc:DisplayName>" + user.Name + "</pc:DisplayName><pc:AccountId>" + user.LoginName + "</pc:AccountId><pc:AccountType>User</pc:AccountType></pc:Person>";
                            xPathNav.AppendChild(pcValue);

                        }
                        catch
                        {
                            SPFieldUserValueCollection userValues = item[fieldTitle] as SPFieldUserValueCollection;

                            if (userValues != null)
                                foreach (SPFieldUserValue userValue in userValues)
                                {
                                    SPUser user = userValue.User;
                                    if (user != null)
                                    {
                                        pcValue = "<pc:Person><pc:DisplayName>" + user.Name + "</pc:DisplayName><pc:AccountId>" + user.LoginName + "</pc:AccountId><pc:AccountType>User</pc:AccountType></pc:Person>";
                                        xPathNav.AppendChild(pcValue);
                                    }
                                    else
                                    {
                                        SPGroup group = Web.Groups.GetByID(userValue.LookupId);
                                        pcValue = "<pc:Person><pc:DisplayName>" + group.Name + "</pc:DisplayName><pc:AccountId>" + group.LoginName + "</pc:AccountId><pc:AccountType>Group</pc:AccountType></pc:Person>";
                                        xPathNav.AppendChild(pcValue);
                                    }
                                }
                        }
                    }
                }
            });

        }

        private void InsertIntoCheckBoxType(string fieldValue, XPathNavigator xPathNav, string fieldName)
        {
            fieldName = fieldName + "_1";
            SPFieldMultiChoiceValue choiceValue = new SPFieldMultiChoiceValue(fieldValue);

            string myNamespace = "xmlns:my=\"http://tempuri.org/\"";
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < choiceValue.Count; i++)
            {
                sb.AppendFormat("<tns:{0} {2}>{1}</tns:{0}>", fieldName, choiceValue[i], myNamespace);
            }
            xPathNav.AppendChild(sb.ToString());
        }

        private string GetMulitTextString(string p_Field_String)
        {
            string mComment;
            try
            {

                XmlDocument mDoc = new XmlDocument();
                mDoc.LoadXml(p_Field_String);

                mComment = "<div xmlns=\"http://www.w3.org/1999/xhtml\">" + mDoc.InnerXml + "</div>";

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                mComment = "<div xmlns=\"http://www.w3.org/1999/xhtml\">" + p_Field_String + "</div>";
            }

            return mComment;
        }

        #endregion
    }
}
